using System;
using System.Diagnostics;
using System.Drawing;
using System.Threading;
using System.Windows.Forms;
using Firestarter.DB.Schema.BO;
using FireStarterModeller.BO;
using Firestarter.DB.Schema.Logic;
using Habanero.Base;
using Habanero.BO;
using Habanero.Faces.Base;
using Habanero.Faces.Win;
using DockStyle=System.Windows.Forms.DockStyle;
using Timer = System.Threading.Timer;

namespace Firestarter.DB.Schema.UI
{
    public class ApproveSchemaChangesWizardStep : WizardStepWin
    {
        private IReverseEngineering _reverseEngineering;
        private readonly DatabaseInfoChangesControl _databaseInfoChangesControl;
        private SingleRelationship<DBDatabase> _storedDatabaseInfoRelationship;
        private SchemaMerger _schemaMerger;
        private IGroupBox _loadingChangesGroupBox;
        private IProgressBar _progressBar;
        

        public ApproveSchemaChangesWizardStep()
        {
            IControlFactory factory = GlobalUIRegistry.ControlFactory;
            _databaseInfoChangesControl = new DatabaseInfoChangesControl();
            SetupLoadingChangesGroupBox(factory);
            _databaseInfoChangesControl.Dock = DockStyle.Fill;
            Controls.Add(_databaseInfoChangesControl);
            _loadingChangesGroupBox.Dock = DockStyleWin.GetDockStyle(DockStyle.Fill);
            Controls.Add((Control) _loadingChangesGroupBox);
        }

        private void SetupLoadingChangesGroupBox(IControlFactory factory)
        {
            _loadingChangesGroupBox = factory.CreateGroupBox("Loading Schema Changes");
            BorderLayoutManager layoutManager = factory.CreateBorderLayoutManager(_loadingChangesGroupBox);

            ILabel label = factory.CreateLabel("Please wait. Busy loading schema changes...", true);
            label.Location = new Point(20,20);
         
            IPanel panel = factory.CreatePanel();
            panel.Width = 500;
            panel.Height = 50;
            _progressBar = factory.CreateProgressBar();
            _progressBar.Width = 500;
            _progressBar.Height = 20;
            _progressBar.Location = new Point(50,100);     
            panel.Controls.Add(_progressBar);
            layoutManager.AddControl(label, BorderLayoutManager.Position.North);
            layoutManager.AddControl(panel, BorderLayoutManager.Position.Centre); 
           
        }

        public IReverseEngineering ReverseEngineering
        {
            get { return _reverseEngineering; }
            set
            {
                _reverseEngineering = value;
                UpdateSchemaMerger();
            }
        }

        private void UpdateSchemaMerger()
        {
            SchemaMerger schemaMerger = null;
            if (_reverseEngineering != null) schemaMerger = new SchemaMerger(_reverseEngineering);
            _schemaMerger = schemaMerger;
        }

        public SchemaMerger SchemaMerger
        {
            get { return _schemaMerger; }
            internal set { _schemaMerger = value; }
        }

        private void StoredDatabaseInfoChanged(object sender, BOEventArgs<DBDatabase> e)
        {
            UpdateDatabaseInfo();
        }
        private void UpdateDatabaseInfo()
        {
            IDBDatabase dbDatabase = null;
            if (_reverseEngineering != null)
                dbDatabase = _reverseEngineering.StoredDatabase;
            _databaseInfoChangesControl.Database = dbDatabase as DBDatabase;
        }

        public DatabaseInfoChangesControl DatabaseInfoChangesControl
        {
            get { return _databaseInfoChangesControl; }
        }

        public IGroupBox LoadingChangesGroupBox
        {
            get { return _loadingChangesGroupBox; }
        }

        public DBDatabase StoredDatabase
        {
            get { return _databaseInfoChangesControl.Database; }
        }

        #region Implementation of IWizardStep

        /// <summary>
        ///             Initialises the step. Run when the step is reached.
        /// </summary>
        public override void InitialiseStep()
        {
            Cursor.Current = Cursors.WaitCursor;
            try
            {
                ResetProgressBar();
                UpdateProgressBar(5);
                DatabaseInfoChangesControl.Visible = false;
                UpdateProgressBar(5);
                LoadingChangesGroupBox.Visible = true;
                Update();
                UpdateProgressBar(10);

                _schemaMerger.RunMerge();


                UpdateProgressBar(20);
                SetupStoredDatabaseInfoControl();
                UpdateProgressBar(10);
                LoadingChangesGroupBox.Visible = false;
                DatabaseInfoChangesControl.Visible = true;
                UpdateProgressBar(10);
                Update();
            }
            finally
            {
                Cursor.Current = Cursors.Default;
            }
        }

        private void ResetProgressBar()
        {
            _progressBar.Value = 0;
        }

        private void UpdateProgressBar(int percentageProgress)
        {
            if (percentageProgress >= 100) return;
            _progressBar.Increment(percentageProgress);
            
            _progressBar.ResumeLayout(true);
            this.Refresh();
        }

        private void SetupStoredDatabaseInfoControl()
        {
            if (_storedDatabaseInfoRelationship != null)
            {
                _storedDatabaseInfoRelationship.Updated -= StoredDatabaseInfoChanged;
            }
            var reverseEngineering = _reverseEngineering as ReverseEngineering;
            if (reverseEngineering != null)
            {
                UpdateProgressBar(10);
                _storedDatabaseInfoRelationship = reverseEngineering
                    .Relationships.GetSingle<DBDatabase>("StoredDatabase");
                _storedDatabaseInfoRelationship.Updated += StoredDatabaseInfoChanged;
            }
            UpdateProgressBar(10);
            UpdateDatabaseInfo();
            UpdateProgressBar(10);
        }

        /// <summary>
        ///             Verifies whether this step can be passed.
        /// </summary>
        /// <param name="message">Error message should moving on be disallowed. This message will be displayed to the user by the WizardControl.</param>
        public override bool CanMoveOn(out string message)
        {
            message = null;
            return true;
        }

        /// <summary>
        ///             Verifies whether the user can move back from this step.
        /// </summary>
        public override bool CanMoveBack()
        {
            return true;
        }

        /// <summary>
        ///             Provides an interface for the developer to implement functionality to cancel any edits made as part of this
        ///             wizard step. The default wizard controller functionality is to call all wizard steps cancelStep methods when
        ///             its Cancel method is called.
        /// </summary>
        public override void CancelStep()
        {
            if (_reverseEngineering == null) return;
            if (_reverseEngineering.StoredDatabase == null) return;
            _reverseEngineering.StoredDatabase.CancelEdits();
        }

        /// <summary>
        ///             The text that you want displayed at the top of the wizard control when this step is active.
        /// </summary>
        public override string HeaderText
        {
            get { return "Approve the Reverse Engineered database schema changes."; }
        }

        #endregion
    }
}
